package com.example.config;

import com.example.common.RequireDataPermission;
import com.example.common.RequirePermission;
import com.example.entity.Permission;
import com.example.service.DataPermissionService;
import com.example.service.PermissionService;
import com.example.util.UserContextUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 权限拦截器
 * 处理@RequirePermission注解的权限验证
 */
@Component
public class PermissionInterceptor implements HandlerInterceptor {
    
    @Autowired
    private UserContextUtil userContextUtil;
    
    @Autowired
    private PermissionService permissionService;

    @Autowired
    private DataPermissionService dataPermissionService;

    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果不是HandlerMethod，直接放行
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        
        // 检查方法上是否有@RequirePermission注解
        RequirePermission requirePermission = method.getAnnotation(RequirePermission.class);
        if (requirePermission == null) {
            // 检查类上是否有@RequirePermission注解
            requirePermission = handlerMethod.getBeanType().getAnnotation(RequirePermission.class);
        }
        
        // 如果没有权限注解，直接放行
        if (requirePermission == null) {
            return true;
        }
        
        // 检查用户是否已认证
        if (!userContextUtil.isAuthenticated()) {
            writeErrorResponse(response, 401, "用户未登录", "请先登录系统");
            return false;
        }
        
        // 获取当前用户ID
        Long userId = userContextUtil.getCurrentUserId();
        if (userId == null) {
            writeErrorResponse(response, 401, "获取用户信息失败", "用户认证状态异常，请重新登录");
            return false;
        }
        
        // 获取用户权限列表
        List<String> userPermissions = permissionService.getUserPermissions(userId);
        
        // 检查用户是否拥有所需权限
        String requiredPermission = requirePermission.value();
        if (!userPermissions.contains(requiredPermission)) {
            // 获取权限的详细信息
            String permissionDescription = getPermissionDescription(requiredPermission);
            String errorMessage = "权限不足，需要权限：" + requiredPermission;
            String detailMessage = "您没有访问此资源的权限";
            
            if (permissionDescription != null && !permissionDescription.isEmpty()) {
                detailMessage = "您缺少以下权限：" + permissionDescription + "（" + requiredPermission + "）";
            }
            
            writeEnhancedErrorResponse(response, 403, errorMessage, detailMessage, requiredPermission, permissionDescription);
            return false;
        }

        // 检查数据权限
        RequireDataPermission dataPermission = method.getAnnotation(RequireDataPermission.class);
        if (dataPermission != null) {
            if (!checkDataPermission(request, userId, dataPermission)) {
                String dataPermissionType = dataPermission.value().toString();
                String resourceType = dataPermission.resourceType();
                String errorMessage = "数据权限不足";
                String detailMessage = "您没有访问此数据的权限，需要数据权限类型：" + getDataPermissionDescription(dataPermissionType) + 
                                     "，资源类型：" + getResourceTypeDescription(resourceType);
                
                writeEnhancedErrorResponse(response, 403, errorMessage, detailMessage, 
                    "DATA:" + dataPermissionType + ":" + resourceType, 
                    "数据权限：" + getDataPermissionDescription(dataPermissionType));
                return false;
            }
        }

        return true;
    }
    
    /**
     * 获取权限描述
     */
    private String getPermissionDescription(String permissionCode) {
        try {
            return permissionService.getPermissionDescription(permissionCode);
        } catch (Exception e) {
            return null;
        }
    }
    
    /**
     * 获取数据权限类型的描述
     */
    private String getDataPermissionDescription(String dataPermissionType) {
        switch (dataPermissionType) {
            case "SELF_ONLY":
                return "仅可访问自己的数据";
            case "DEPARTMENT":
                return "可访问本部门数据";
            case "DEPARTMENT_AND_SUB":
                return "可访问本部门及下级部门数据";
            case "ALL":
                return "可访问所有数据";
            case "CUSTOM":
                return "自定义数据权限";
            default:
                return "未知数据权限类型";
        }
    }
    
    /**
     * 获取资源类型的描述
     */
    private String getResourceTypeDescription(String resourceType) {
        switch (resourceType) {
            case "user":
                return "用户数据";
            case "role":
                return "角色数据";
            case "menu":
                return "菜单数据";
            case "permission":
                return "权限数据";
            case "organization":
                return "组织数据";
            case "appointment":
                return "预约数据";
            case "purchase":
                return "购买记录数据";
            case "schedule":
                return "排班数据";
            case "notice":
                return "通知数据";
            default:
                return resourceType;
        }
    }
    
    /**
     * 检查数据权限
     */
    private boolean checkDataPermission(HttpServletRequest request, Long userId, RequireDataPermission dataPermission) {
        try {
            // 从请求路径中提取资源ID
            String pathInfo = request.getRequestURI();
            String[] pathParts = pathInfo.split("/");

            // 简化实现：假设资源ID在路径的最后一部分
            Long resourceId = null;
            if (pathParts.length > 0) {
                String lastPart = pathParts[pathParts.length - 1];
                try {
                    resourceId = Long.parseLong(lastPart);
                } catch (NumberFormatException e) {
                    // 如果最后一部分不是数字，可能是其他操作，暂时允许通过
                    return true;
                }
            }

            // 如果没有资源ID，检查是否为列表查询等操作
            if (resourceId == null) {
                // 对于列表查询，检查用户是否有基本权限
                return dataPermissionService.hasDataPermission(userId, dataPermission.resourceType(),
                        null, dataPermission.value());
            }

            // 检查对特定资源的权限
            return dataPermissionService.hasDataPermission(userId, dataPermission.resourceType(),
                    resourceId, dataPermission.value());
        } catch (Exception e) {
            // 权限检查出错时，默认拒绝访问
            return false;
        }
    }

    /**
     * 写入错误响应
     */
    private void writeErrorResponse(HttpServletResponse response, int code, String message, String detail) throws IOException {
        response.setStatus(code);
        response.setContentType("application/json;charset=UTF-8");

        Map<String, Object> result = new HashMap<>();
        result.put("code", code);
        result.put("message", message);
        result.put("detail", detail);
        result.put("data", null);

        response.getWriter().write(objectMapper.writeValueAsString(result));
    }
    
    /**
     * 写入增强的错误响应
     */
    private void writeEnhancedErrorResponse(HttpServletResponse response, int code, String message, 
                                          String detail, String requiredPermission, String permissionDescription) throws IOException {
        response.setStatus(code);
        response.setContentType("application/json;charset=UTF-8");

        Map<String, Object> result = new HashMap<>();
        result.put("code", code);
        result.put("message", message);
        result.put("detail", detail);
        
        // 权限详细信息
        Map<String, Object> permissionInfo = new HashMap<>();
        permissionInfo.put("requiredPermission", requiredPermission);
        permissionInfo.put("permissionDescription", permissionDescription);
        permissionInfo.put("suggestions", "请联系管理员为您分配相应权限，或切换到有权限的账号");
        
        result.put("permissionInfo", permissionInfo);
        result.put("data", null);

        response.getWriter().write(objectMapper.writeValueAsString(result));
    }
} 